package ar.com.profertil.galicia.analizer;

import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import ar.com.profertil.galicia.entity.DetalleDEnvio;
import ar.com.profertil.galicia.entity.DetalleEEnvio;
import ar.com.profertil.galicia.entity.HeaderEnvio;
import ar.com.profertil.galicia.entity.TrailerEnvio;

/**
 * The Class AnalizerEnvioDeuda.
 * 
 * @author augusto.ferrari@softtek.com
 * 
 *         Esta clase presenta metodos para recuperar las diferentes estructuras
 *         del archivo de entrada.
 */
public class AnalizerEnvioDeuda implements Serializable {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = -2817426977536742390L;

	/** The header. */
	private HeaderEnvio header;

	/** The detalle e. */
	private DetalleEEnvio[] detalleE;

	/** The detalle d. */
	private DetalleDEnvio[] detalleD;

	/** The trailer. */
	private TrailerEnvio trailer;

	/**
	 * Inicializar.
	 * 
	 * @param cabecera
	 *            the cabecera
	 * @param detallesD
	 *            the detalles d
	 * @param detallesE
	 *            the detalles e
	 * @param cierre
	 *            the cierre
	 * @throws Exception
	 */
	public void inicializar(String cabecera, String[] detallesD,
			String[] detallesE, String cierre) throws Exception {
		this.header = parsearHeader(cabecera);
		this.detalleD = parsearDetallesD(detallesD);
		this.detalleE = parsearDetallesE(detallesE);
		this.trailer = parsearTrailer(cierre);
	}

	/**
	 * Gets the header.
	 * 
	 * @return the header
	 */
	public HeaderEnvio getHeader() {
		return header;
	}

	/**
	 * Gets the detalle d.
	 * 
	 * @return the detalle d
	 */
	public DetalleDEnvio[] getDetalleD() {
		return detalleD;
	}

	/**
	 * Gets the detalle e.
	 * 
	 * @return the detalle e
	 */
	public DetalleEEnvio[] getDetalleE() {
		return detalleE;
	}

	/**
	 * Gets the trailer.
	 * 
	 * @return the trailer
	 */
	public TrailerEnvio getTrailer() {
		return trailer;
	}

	// Metodo para recuperar los atributos del Header.
	/**
	 * Parsear header.
	 * 
	 * @param cabecera
	 *            the cabecera
	 * @return the header envio
	 * @throws IOException
	 * @throws SAXException
	 */
	private HeaderEnvio parsearHeader(String cabecera) throws Exception {

		HeaderEnvio header = new HeaderEnvio();

		// Crear el documento XML.
		Document doc = convertirADom(cabecera);
		NodeList nodos = recuperarNodos(doc, "ZHEADER");
		Node nodo = nodos.item(0);

		// Recuperar los datos y llenar el Header.
		if (nodo.getNodeType() == Node.ELEMENT_NODE) {

			Element zHeader = (Element) nodo;

			header.setCodigoRegistro(getString(zHeader, "ZCODREG"));
			header.setIdentificadorEmpresa(getString(zHeader, "ZIDEMPRESA"));
			header.setFechaProceso(getString(zHeader, "ZFECHA"));
			header.setHoraProceso(getString(zHeader, "ZHORA"));
			header.setNumeroArchivo(getString(zHeader, "ZARCHIVO"));
			header.setFiller(getString(zHeader, "ZESPACIO"));
		}

		return header;
	}

	// Metodo para recuperar los atributos de los DetalleD.
	/**
	 * Parsear detalles d.
	 * 
	 * @param detalles
	 *            the detalles
	 * @return the detalle d envio[]
	 * @throws IOException
	 * @throws SAXException
	 */
	private DetalleDEnvio[] parsearDetallesD(String[] detalles)
			throws SAXException, IOException {

		DetalleDEnvio[] detallesD = new DetalleDEnvio[detalles.length];

		// Iterar para cada nodo.
		for (int i = 0; i < detalles.length; i++) {

			DetalleDEnvio detail = new DetalleDEnvio();

			// Crear el documento XML.
			Document doc = convertirADom(detalles[i]);
			NodeList nodos = recuperarNodos(doc, "ZDETALLE_D");
			Node nodo = nodos.item(0);

			// Recuperar los datos y llenar el DetalleD.
			if (nodo.getNodeType() == Node.ELEMENT_NODE) {

				Element zDetalle = (Element) nodo;

				detail.setCodigoRegistro(getString(zDetalle, "ZCODREG"));
				detail.setTipoIdentificacionCliente(getString(zDetalle,
						"ZTCLIENTE"));
				detail.setIdentificacionCliente(getString(zDetalle, "ZCLIENTE"));
				detail.setIdentificacionInternaCliente(getString(zDetalle,
						"ZIDCLIENTE"));
				detail.setTipoDocumento(getString(zDetalle, "ZTDOC"));
				detail.setIdentificacionDocumento(getString(zDetalle, "ZIDDOC"));
				detail.setFechaVigencia(getString(zDetalle, "ZVIGENCIA"));
				detail.setImporte1(getString(zDetalle, "ZIMPORTE1"));
				detail.setFechaVencimiento1(getString(zDetalle, "ZVTO1"));
				detail.setImporte2(getString(zDetalle, "ZIMPORTE2"));
				detail.setFechaVencimiento2(getString(zDetalle, "ZVTO2"));
				detail.setImporte3(getString(zDetalle, "ZIMPORTE3"));
				detail.setFechaVencimiento3(getString(zDetalle, "ZVTO3"));
				detail.setNombreCliente(getString(zDetalle, "ZNOMCLI"));
				detail.setIdentificacionInternaDocumento(getString(zDetalle,
						"ZIDINTDOC"));
				detail.setDivision(getString(zDetalle, "ZDIVISION"));
				detail.setCodigoMoneda(getString(zDetalle, "ZMONEDA"));
				detail.setLeyenda1(getString(zDetalle, "ZLEYENDA1"));
				detail.setLeyenda2(getString(zDetalle, "ZLEYENDA2"));
				detail.setFiller(getString(zDetalle, "ZESPACIO"));

				detallesD[i] = detail;
			}
		}

		return detallesD;
	}

	// Metodo para recuperar los atributos de los DetalleE.
	/**
	 * Parsear detalles e.
	 * 
	 * @param detalles
	 *            the detalles
	 * @return the detalle e envio[]
	 * @throws IOException
	 * @throws SAXException
	 */
	private DetalleEEnvio[] parsearDetallesE(String[] detalles)
			throws SAXException, IOException {

		DetalleEEnvio[] detallesE = new DetalleEEnvio[detalles.length];

		// Iterar para cada nodo.
		for (int i = 0; i < detalles.length; i++) {

			DetalleEEnvio detail = new DetalleEEnvio();

			// Crear el documento XML.
			Document doc = convertirADom(detalles[i]);
			NodeList nodos = recuperarNodos(doc, "ZDETALLE_E");
			Node nodo = nodos.item(0);

			// Recuperar los datos y llenar el DetalleE.
			if (nodo.getNodeType() == Node.ELEMENT_NODE) {

				Element zDetalle = (Element) nodo;

				detail.setCodigoRegistro(getString(zDetalle, "ZCODREG"));
				detail.setEmail1(getString(zDetalle, "ZEMAIL1"));
				detail.setEmail2(getString(zDetalle, "ZEMAIL2"));
				detail.setEmail3(getString(zDetalle, "ZEMAIL3"));
				detail.setChequeTercero(getString(zDetalle, "ZCHEQUE_TER"));
				detail.setChequeDiferido(getString(zDetalle, "ZCHEQUE_DIF"));
				detail.setFechaDiferimiento(getString(zDetalle, "ZFECHA_DIF"));
				detail.setDiasDiferimiento(getString(zDetalle, "ZDIAS_DIF"));
				detail.setFiller(getString(zDetalle, "ZESPACIO"));

				detallesE[i] = detail;
			}
		}

		return detallesE;
	}

	// Metodo para recuperar los atributos del Trailer.
	/**
	 * Parsear trailer.
	 * 
	 * @param cierre
	 *            the cierre
	 * @return the trailer envio
	 * @throws IOException
	 * @throws SAXException
	 */
	private TrailerEnvio parsearTrailer(String cierre) throws SAXException,
			IOException {
		TrailerEnvio trailer = new TrailerEnvio();
		// Crear el documento XML.
		Document doc = convertirADom(cierre);
		NodeList nodos = recuperarNodos(doc, "ZTRAILER");
		Node nodo = nodos.item(0);
		// Recuperar los datos y llenar el Header.
		if (nodo.getNodeType() == Node.ELEMENT_NODE) {
			Element zTrailer = (Element) nodo;
			trailer.setCodigoRegistro(getString(zTrailer, "ZCODREG"));
			trailer.setCantidadRegistros(getString(zTrailer, "ZCANREG"));
			trailer.setFiller(getString(zTrailer, "ZESPACIO")
					+ getString(zTrailer, "ZESPACIO1"));
		}
		return trailer;
	}

	// Metodo para convertir la cadena a documento XML.
	/**
	 * Convertir a dom.
	 * 
	 * @param xml
	 *            the xml
	 * @return the document
	 * @throws IOException
	 * @throws SAXException
	 */
	private Document convertirADom(String xml) throws SAXException, IOException {
		Document doc = null;
		DOMParser parser = new DOMParser();
		parser.parse(new InputSource(new StringReader(xml)));
		doc = parser.getDocument();
		return doc;
	}

	// Metodo para recuperar los nodos del documento XML.
	/**
	 * Recuperar nodos.
	 * 
	 * @param doc
	 *            the doc
	 * @param etiqueta
	 *            the etiqueta
	 * @return the node list
	 */
	private NodeList recuperarNodos(Document doc, String etiqueta) {
		NodeList listaNodos = doc.getElementsByTagName(etiqueta);
		return listaNodos;
	}

	// Metodo para recuperar los elementos de un nodo.
	/**
	 * Recuperar elementos.
	 * 
	 * @param elemento
	 *            the elemento
	 * @param etiqueta
	 *            the etiqueta
	 * @return the node list
	 */
	private NodeList recuperarElementos(Element elemento, String etiqueta) {
		NodeList elementos = elemento.getElementsByTagName(etiqueta);
		return elementos;
	}

	// Metodo para recuperar el valor de una etiqueta.
	/**
	 * Gets the string.
	 * 
	 * @param elemento
	 *            the elemento
	 * @param etiqueta
	 *            the etiqueta
	 * @return the string
	 */
	private String getString(Element elemento, String etiqueta) {
		String retorno = "";
		NodeList nodosDentro = recuperarElementos(elemento, etiqueta);
		Element element = (Element) nodosDentro.item(0);
		if (element != null) {
			NodeList nodeList = element.getChildNodes();
			if (nodeList != null && nodeList.getLength() > 0) {
				Node hijo = nodeList.item(0);
				if (hijo != null) {
					retorno = hijo.getNodeValue();
				}
			}
		}
		return retorno;
	}
}
